//
//  ViewController.swift
//  UIKit物理效果
//
//  Created by 柯南 on 2022/9/15.
//

//MARK:- 物理效果联系
import UIKit

class ViewController: UIViewController {
    
    // 物理控制中心
    lazy var animator = UIDynamicAnimator(referenceView: self.view)
    
    // 演示视图1
    lazy var dynamicItem1View: UIView = {
        let itemView = UIView(frame: .init(x: 100, y: 300, width: 50, height: 50))
        itemView.backgroundColor = .blue
        itemView.layer.cornerRadius = 25
        return itemView
    }()
    
    // 演示视图2
    lazy var dynamicItem2View: UIView = {
        let itemView = UIView(frame: .init(x: 160, y: 250, width: 100, height: 100))
        itemView.backgroundColor = .black
        itemView.layer.cornerRadius = 50
        return itemView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .orange
        
        self.view.addSubview(dynamicItem1View)
        self.view.addSubview(dynamicItem2View)
        
//        重力_UIGravityBehavior()
        碰撞_UICollisionBehavior()
//        吸附_UIAttachmentBehavior()
//        推动_UIPushBehavior()
//        捕获_UISnapBehavior()
        
        其他配置_UIDynamicItemBehavior()
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.navigationController?.pushViewController(ViewController2(), animated: true)
    }

    func 重力_UIGravityBehavior() {
        let gravity = UIGravityBehavior(items: [dynamicItem1View])
        
        // 重力向量
//        gravity.gravityDirection = .init(dx: 0.5, dy: 0.5)
        
        // 重力方向, 以弧度表示 pi = 360度 ，也就是向左
//        gravity.angle = .pi
        
        // 重力大小
        gravity.magnitude = 2
        
        animator.addBehavior(gravity)
    }
    
    func 碰撞_UICollisionBehavior() {
        let collosionBehavior = UICollisionBehavior(items: [dynamicItem1View, dynamicItem2View])
        // 以 ReferenceView 为边界
        collosionBehavior.translatesReferenceBoundsIntoBoundary = true
        
        // 设置碰撞类型, items 元素间碰撞，boundaries 边界碰撞, everything 所有碰撞
        collosionBehavior.collisionMode = .everything
        
        // 碰撞【边界的内边距】
//        collosionBehavior.setTranslatesReferenceBoundsIntoBoundary(with: .init(top: 50, left: 50, bottom: 50, right: 50))
        
        // 自定义碰撞边界-1， 通过贝塞尔曲线添加碰撞边界
//        let path = UIBezierPath(rect: .init(x: 50, y: 50, width: 200, height: 200))
//        path.lineWidth = 1
//        path.lineCapStyle = .round
//        path.lineJoinStyle = .round
//        collosionBehavior.addBoundary(withIdentifier: "path" as NSCopying, for: path)
        
        // 自定义碰撞边界-2，通过一条线段设置边界
//        collosionBehavior.addBoundary(withIdentifier: "path123" as NSCopying,
//                                      from: .init(x: 0, y: 350),
//                                      to: .init(x: 220, y: 500))
        
        animator.addBehavior(collosionBehavior)
    }
    
    func 吸附_UIAttachmentBehavior() {
        // 元素吸附锚点
        let attachementBehavior = UIAttachmentBehavior(item: dynamicItem1View, attachedToAnchor: .init(x: 175, y: 250))
        
        // 元素吸附锚点，并给一个25的力
//        let attachementBehavior = UIAttachmentBehavior(item: dynamicItem1View, offsetFromCenter: .init(horizontal: 25, vertical: 0), attachedToAnchor: .init(x: 175, y: 250))
        
        // 元素与元素之间吸附
//        let attachementBehavior = UIAttachmentBehavior(item: dynamicItem1View, attachedTo: dynamicItem2View)
        
        // 元素与锚点，或元素与元素之间的距离
        attachementBehavior.length = 100
        
        // 在发生弹性吸附时震动的频率，值越大，弹性运动的频率越快
        attachementBehavior.frequency = 0.5
        
        // 设置元素在弹性吸附时震动所受到的阻力，值越大，阻力越大，弹性运动震动的幅度越小
//        attachementBehavior.damping = 1
        
        // 旋转阻力 指围绕一点旋转所受的阻力，默认值0.0，值越大，阻力越大
//        attachementBehavior.frictionTorque = 1
        
        
        
        animator.addBehavior(attachementBehavior)
    }
    
    func 推动_UIPushBehavior() {
        // continuous: 连续的推动, instantaneous: 瞬间的推动
        let pushBehavior = UIPushBehavior(items: [dynamicItem1View], mode: .instantaneous)
        
        // 推力矢量方向
        pushBehavior.pushDirection = .init(dx: 0.5, dy: 0.5)
        
        // 推力矢量大小
        pushBehavior.magnitude = 1
        
        animator.addBehavior(pushBehavior)
    }
    
    func 捕获_UISnapBehavior() {
        // snapTo 捕获的点, 即元素会朝着捕获点移动
        let snapBehavior = UISnapBehavior(item: dynamicItem1View, snapTo: .init(x: 200, y: 400))
        
        // 修改新的捕获点
//        snapBehavior.snapPoint
        
        // 震动阻尼， 有效范围为0.0~1.0，0.0最大震荡、1.0最小震荡，默认值为0.5
        snapBehavior.damping = 1.0
        
        animator.addBehavior(snapBehavior)
    }
    
    // 可以为一个动态元素设置更多较为具体的动力学属性
    func 其他配置_UIDynamicItemBehavior() {
        let itemBehavior = UIDynamicItemBehavior(items: [dynamicItem2View])
        
        // 弹性系数 用于碰撞行为的动态元素的弹性量。默认值为0.0，有效范围从0.0(没有碰撞)到1.0(完全碰撞)
        itemBehavior.elasticity = 1.0
        
        // 摩擦系数 用于两个发生摩擦的动态元素。默认值0.0(没有摩擦)，当值为1.0时，强烈摩擦。如果设置更高的摩擦，可以使用更高的数值。
//        itemBehavior.friction = 1.0
        
        // 相对质量密度 用于动态元素相对密度。其连同动态元素大小，决定动态元素的有效质量。其参与的动力学行为包括摩擦、碰撞、推动等
        // 默认 1.0
        // 假设你有两个具有相同密度但大小不同的动态元素：元素一尺寸为100x100像素点，元素二尺寸为100x200像素点。
        // 这个例子中，元素二的有效质量是元素一的两倍。
        // 在一个弹性碰撞中，这些元素根据它们的相对质量表现出自然的动量守恒。元素一密度为1.0，
        // 当施加一个力(通过推动行为)1.0级时，加速度为100点/s²。
//        itemBehavior.density = 1
        
        // 线速度阻尼, 用于动态元素所受线速度阻尼大小,
        // 默认值是0.0。有效范围从0.0(没有速度阻尼)到CGFLOAT_MAX(最大速度阻尼)。
        // 当设置为1.0，动态元素会立马停止就像没有力量作用于它一样。
//        itemBehavior.resistance = 0
        
        // 角速度阻尼，用于动态元素所受角速度阻尼大小
        // 有效范围从0.0到CGFLOAT_MAX，值越大，角速度阻尼越大，旋转减速越快，到停止
//        itemBehavior.angularResistance = 0
        
        // 电荷 电荷数确定动态元素与电场和磁场相互作用的程度。
        // 这个属性值没有单位，电磁场强度由你调控的适当的值来决定。默认值0.0z
//        itemBehavior.charge = 20
        
        // 是否固定, 用于指定动态元素是否固定在当前位置
        // 当一个动态元素被设置为固定后，该元素参与碰撞，但不受碰撞影响，仿佛成为一个碰撞边界。默认值为NO
//        itemBehavior.isAnchored = true
        
        
        animator.addBehavior(itemBehavior)
    }
}

